﻿#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;

//LIME 算法类
class LIME
{
public:
    LIME(){}

    //初始照度图估计
    Mat maxMAT(Mat input) {

        Mat output(input.size(), CV_32FC1);
        uchar temp;
        for (int i = 0; i < input.size().height; i++) {
            for (int j = 0; j < input.size().width; j++) {
                temp = fmax(input.at<Vec3f>(i, j)[0], input.at<Vec3f>(i, j)[1]);
                output.at<float>(i, j) = fmax(input.at<Vec3f>(i, j)[2], temp);
            }
        }
        return output;
    }

    //通道转换
    Mat Repeat(Mat& m) {
        int he = m.size().height;
        int wi = m.size().width;
        Mat R(he, wi, CV_32FC3);
        for (int i = 0; i < he; i++) {
            for (int j = 0; j < wi; j++) {
                R.at<Vec3f>(i, j)[0] = m.at<float>(i, j);
                R.at<Vec3f>(i, j)[1] = m.at<float>(i, j);
                R.at<Vec3f>(i, j)[2] = m.at<float>(i, j);
            }
        }
        return R;
    }

    //x方向权重矩阵
    Mat get_wx(Mat &img){
        Mat grad_x;
        Scharr(img, grad_x, -1, 1, 0);
        Mat Wh;
        Wh = 1 / (cv::abs(grad_x) + 1);
        return Wh;
    }

    //y方向权重矩阵
    Mat get_wy(Mat &img){
        Mat grad_y;
        Scharr(img, grad_y, -1, 0, 1);
        Mat Wv;
        Wv = 1 / (cv::abs(grad_y) + 1);
        return Wv;
    }

    //LIME算法整个流程
    Mat run(Mat &img1)
    {
        int he = img1.size().height;
        int wi = img1.size().width;

        img1.convertTo(img1, CV_32FC3);
        Mat img = maxMAT(img1);

        Mat Wv = get_wy(img);
        Mat Wh = get_wx(img);
        Mat re = Wv + Wh;
        
        cv::Mat I = cv::Mat::ones(he, wi, CV_32F);
        I = I + re;
        I = I + img;
        I = I / 255;
        cv::pow(I, 0.6, I);
        Mat I_out = Repeat(I);
        Mat Re = img1 / (I_out);
        return Re;
    }
};

